#include "DBoW2/DBoW2.h"
#include "DBoW2/FORB.h"
#include "DBoW2/TemplatedVocabulary.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>



using namespace cv;
using namespace std;
using namespace DBoW2;


typedef TemplatedVocabulary<DBoW2::FORB::TDescriptor, DBoW2::FORB> ORBVocabulary;


int main( int argc, char** argv )
{

    ORBVocabulary vvocab("/home/xyt/pro/dobw2/bin/vocabulary.yml.gz");

    // read the image 
    cout<<"reading images... "<<endl;
    vector<Mat> images; 
    ifstream fin("./location.txt");
    string temp;
    while (fin >> temp)
    {
        images.push_back(imread(temp));
    }
    cout<<"reading images finish " << images.size() << endl;
    // detect ORB features
    cout<<"detecting ORB features ... "<<endl;
    Ptr< Feature2D > detector = ORB::create();
    vector<Mat> descriptors;
    vector<vector<cv::Mat > > features;
    features.clear();

    for ( Mat& image:images )
    {
        vector<KeyPoint> keypoints; 
        Mat descriptor;
        detector->detectAndCompute( image, Mat(), keypoints, descriptor );
        descriptors.push_back(descriptor);
    }
    
    for (int i = 0; i < descriptors.size(); i++){
        cv::Mat tmpdescriptor = descriptors[i];
        features.push_back(vector<cv::Mat>());
        for (int j = 0; j < tmpdescriptor.rows; j++)
        {
            features.back().push_back(tmpdescriptor.row(j));
        }
    }
    // create vocabulary 
    cout<<"creating vocabulary ... "<<endl;
    
    const int K = 10;   
    const int L = 5;
    const WeightingType weight = TF_IDF;
    const ScoringType score = L1_NORM;

    ORBVocabulary vocab(K, L, weight, score);

    vocab.create(features);
    cout<<"vocabulary info: "<<vocab<<endl;
    vocab.save( "vocabulary.txt" );
    // vocab.saveToBinaryFile("vocabulary.bin");
    cout<<"done"<<endl;
    
    return 0;
}